/***********************************************************************************/
/* Code license:  GNU General Public License v3                                    */
/* Main page:     https://code.google.com/p/library-cross-platform/                */
/* Issue tracker: https://code.google.com/p/library-cross-platform/issues/list     */
/***********************************************************************************/

#include "asciiparser.h"
#include <algorithm>
#include <string>
#include <cctype>

using namespace std;

START_STATE_MAP(parserstate, asciiparser)
END_STATE_MAP()

asciiparser::asciiparser()
{
}

asciiparser::asciiparser(std::istream* stream) : parserstate(stream)
{
}

asciiparser::~asciiparser()
{
}

bool asciiparser::eos(char &c)
{
  return (c == '\n' || c == '\r' || c == '\0') ? true : false;
}

READ_FILE_RESULT asciiparser::skipEmptyLines()
{
  READ_FILE_RESULT out        = FILE_RESULT_OK;
  string           local_data = getRawData();

  if(isEmptyString(local_data) == true) {
    do {
      out = readRawData(local_data);
    }while(out == FILE_RESULT_SIZE_ZERO && out != FILE_RESULT_EOF);
  }
  setRawData(local_data);
  return out;
}

int asciiparser::skipEmptyData(const string &raw_data, int index)
{
  if((unsigned int)index >= raw_data.length())
   return index;

  /* skip ' ' and '\t' */
  while(raw_data[index] != '\r'    &&
        raw_data[index] != '\n'    &&
        raw_data[index] != '\0'    &&
        (raw_data[index] == ' ' || raw_data[index] == '\t'))
  {
    index ++;
  }
  return index;
}

int asciiparser::getDataFromString(const string &raw_data, int raw_index, string &ret_data)
{
  return getDataFromString(raw_data, raw_index, ',', ret_data);
}

int asciiparser::getDataFromString(const string &raw_data, int raw_index, const char separator, string &ret_data)
{
  size_t data_len = raw_data.length();

  ret_data.clear();
  raw_index = skipEmptyData(raw_data, raw_index);

  while(raw_data[raw_index] != '\r'      &&
        raw_data[raw_index] != '\n'      &&
        raw_data[raw_index] != '\0'      &&
        raw_data[raw_index] != ' '       &&
        raw_data[raw_index] != '\t'      &&
        raw_data[raw_index] != separator &&
        (unsigned int)raw_index < data_len )
  {
    ret_data += raw_data[raw_index];
    raw_index ++;
  }

  /* to avoid 'separator' for the next parameter */
  if(raw_data[raw_index] == separator)
    raw_index ++;

  return raw_index;
}

int asciiparser::getParamFromData(const string &raw_data, int raw_index, int paramid, string &ret_data)
{
  return getParamFromData(raw_data, raw_index, ',', paramid, ret_data);
}

int asciiparser::getParamFromData(const string &raw_data, int raw_index, const char separator, int paramid, string &ret_data)
{
  int local_count = 0;
  for(; local_count <= paramid; local_count++)
   raw_index = getDataFromString(raw_data, raw_index, separator, ret_data);
  return raw_index;
}

string asciiparser::parseDataParameter(const string &in, const char c)
{
  int    pos   = 0;
  string name;
  string out;

  pos = skipEmptyData(in, 0);
  pos = in.find(c, pos);
  pos = pos + 1; /* skip separator 'c' */
  pos = skipEmptyData(in, pos);
  strcpytill(in, pos, '\n', &out);

  return out;
}

/* parse string
 * IN:  string format: name_value:   data_value
 * OUT: out.name  = name_value
 *      out.value = data_value
 */
param_value asciiparser::parseDataParameter(const string &in, int index, const char separator)
{
  param_value out;
  int in_length = in.length();
  index = skipEmptyData(in, index);
  index = strcpytill(in, index, separator, &out.name);
  if(out.name.length() == 0 || out.name.at(0) == '\0')
   out.name.clear();

  if(index >= in_length)
  {
    out.value.clear();
    return out;
  }

  index ++; /* skip separator */
  index = skipEmptyData(in, index);
  if(index >= in_length)
  {
    out.value.clear();
    return out;
  }

  index = strcpytill(in, index, '\n', &out.value);
  if(out.value.at(0) == '\0' || out.name.length() == 0)
   out.value.clear();

  return out;
}

int asciiparser::strcpytill(const string &in, int index, const char till, string *out)
{
  if((unsigned int)index >= in.length())
   return -1;

  while(in[index] != till &&
        in[index] != '\n' &&
        in[index] != '\r' &&
        in[index] != '\0' )
  {
    out->push_back(in[index++]);
  }

  return index;
}

bool asciiparser::isEmptyString(const string &in)
{
  if(in.length() == 0)
   return true;
  else
   return ( in.at(0) == '\n' || in.at(0) == '\r' || in.at(0) == '\0') ? true : false;
}

bool asciiparser::isComment()
{
  return false;
}

void asciiparser::remove_space(string& str)
{
  str.erase(remove_if(str.begin(), str.end(), (int(*)(int))isspace), str.end());
}

void asciiparser::remove_eof_string(string& str)
{
  str.erase(remove_if(str.begin(), str.end(), ch_eof_string()), str.end());
}

